// 默认参数
var stop;
var MOUSE_SPEED = 0.005;
var NAV_DELTA = 45;
var FAR = 1000;
var USE_DEPTH = true;
document.panoJsonCache = "";

// 全局变量
var WIDTH, HEIGHT;
var currHeading = 0;
var centerHeading = 0;
var navList = [];
var headingVector = new THREE.Euler();
var moveVector = new THREE.Vector3();
var HMDRotation = new THREE.Quaternion();
var BaseRotation = new THREE.Quaternion();
var BaseRotationEuler = new THREE.Euler();

// Utility function
function getQueryString(name) {
  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  var r = window.location.search.substr(1).match(reg);
  if (r != null) return unescape(r[2]);
  return null;
}

function angleRangeDeg(angle) {
  angle %= 360;
  if (angle < 0) angle += 360;
  return angle;
}

function angleRangeRad(angle) {
  angle %= 2 * Math.PI;
  if (angle < 0) angle += 2 * Math.PI;
  return angle;
}

function deltaAngleDeg(a, b) {
  return Math.min(360 - (Math.abs(a - b) % 360), Math.abs(a - b) % 360);
}

function deltaAngleRas(a, b) {
  // todo
}

// ----------------------------------------------
function initWebGL() {
  WIDTH = window.innerWidth;
  HEIGHT = window.innerHeight;
  // create streetScene
  streetScene = new THREE.Scene();
  triangleShape = "";
  mouseX = 0;
  mouseY = 0;
  mouseOnBall = "";
  mesh = "";
  // Create camera
  streetCamera = new THREE.PerspectiveCamera(60, WIDTH / HEIGHT, 0.1, FAR);
  streetCamera.target = new THREE.Vector3(1, 0, 0);
  streetCamera.useQuaternion = true;
  streetScene.add(streetCamera);

  // light
  var dirLight = new THREE.DirectionalLight(0xffffff);
  dirLight.position.set(200, 200, 1000).normalize();

  streetCamera.add(dirLight);
  streetCamera.add(dirLight.target);

  // Add projection sphere
  projSphere = new THREE.Mesh(
    new THREE.SphereGeometry(500, 512, 256),
    new THREE.MeshBasicMaterial({
      map: THREE.ImageUtils.loadTexture(""),
      side: THREE.DoubleSide,
    })
  );
  projSphere.geometry.dynamic = true;
  projSphere.useQuaternion = true;
  streetScene.add(projSphere);
  var material = new THREE.MeshLambertMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide,
  });
  try {
    renderer = new THREE.WebGLRenderer();
  } catch (e) {
    alert("This application needs WebGL enabled!");
    return false;
  }

  renderer.autoClearColor = false;
  renderer.setSize(WIDTH, HEIGHT);
  // renderer.setClearColor( 0x000000, 1 );
  var viewer = document.querySelector("#viewer");
  viewer.append(renderer.domElement);
}

function initShape() {
  triangleShape = new THREE.Shape();
  triangleShape.moveTo(8, 2);
  triangleShape.lineTo(4, 8);
  triangleShape.lineTo(12, 8);
  triangleShape.lineTo(8, 2);
  var geometry = new THREE.ShapeGeometry(triangleShape);
  var material = new THREE.MeshBasicMaterial({
    color: new THREE.Color(0xffee00),
    overdraw: 1,
  });
  mesh = new THREE.Mesh(geometry, material);
  mesh.position = new THREE.Vector3(-2, -2, -4);
  mesh.rotation.set(0, 0, 0);
  // mesh.rotation.set(THREE.Math.radToDeg(90*Math.PI/180)) ;
  mesh.scale.set(0.1, 0.1, 0.1);
  geometry.verticesNeedUpdate = true;
  streetScene.add(mesh);
}

function initBuuny() {
  var material = new THREE.MeshLambertMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide,
  });

  var loader = new THREE.VTKLoader();
  loader.addEventListener("load", function (event) {
    var geometry = event.content;
    var mesh = new THREE.Mesh(geometry, material);
    mesh.position = new THREE.Vector3(-1, -1, -3);
    mesh.scale = new THREE.Vector3(1, 1, 1);
    geometry.verticesNeedUpdate = true;
    streetScene.add(mesh);
  });
  loader.load("../models/vtk/bunny.vtk");
}

function wheel(obj, fn, useCapture) {
  var mousewheelevt = /Firefox/i.test(navigator.userAgent)
    ? "DOMMouseScroll"
    : "mousewheel"; //FF doesn't recognize mousewheel as of FF3.x
  if (obj.attachEvent)
    //if IE (and Opera depending on user setting)
    obj.attachEvent("on" + mousewheelevt, handler, useCapture);
  else if (obj.addEventListener)
    //WC3 browsers
    obj.addEventListener(mousewheelevt, handler, useCapture);

  function handler(event) {
    var delta = 0;
    var event = window.event || event;
    var delta = event.detail ? -event.detail / 3 : event.wheelDelta / 120;
    if (event.preventDefault) event.preventDefault();
    event.returnValue = false;
    return fn.apply(obj, [event, delta]);
  }
}

function initControls() {
  // Mouse
  // ---------------------------------------
  var viewer = document.querySelector("#viewer"),
    mouseButtonDown = false,
    lastClientX = 0,
    lastClientY = 0;

  // viewer.dblclick(function() {
  //   moveToNextPlace();
  // });

  var startDown, endDown;
  viewer.addEventListener("mousedown", function (event) {
    startDown = event.timeStamp;
    mouseButtonDown = true;
    lastClientX = event.clientX;
    lastClientY = event.clientY;
    mouseX = event.clientX;
    mouseY = event.clientY;
  });

  viewer.addEventListener("mouseup", function (event) {
    endDown = event.timeStamp;
    if (endDown - startDown > 1000) {
      var enableX = 1;
      BaseRotationEuler.set(
        angleRangeRad(
          BaseRotationEuler.x +
            (event.clientY - lastClientY) * MOUSE_SPEED * enableX
        ),
        angleRangeRad(
          BaseRotationEuler.y + (event.clientX - lastClientX) * MOUSE_SPEED
        ),
        0.0
      );
      lastClientX = event.clientX;
      lastClientY = event.clientY;
      mouseX = event.clientX;
      mouseY = event.clientY;
      BaseRotation.setFromEuler(BaseRotationEuler);
    }
    mouseButtonDown = false;
  });

  var time = 0;
  wheel(document.getElementById("viewer"), function (event, delta) {
    if (delta == 1) {
      if (time < 8) {
        streetCamera.fov -= event.wheelDeltaY * 0.05;
        streetCamera.updateProjectionMatrix();
        time++;
      }
      // camera.position.z += 10;
    }
    if (delta == -1) {
      if (time > -1) {
        streetCamera.fov -= event.wheelDeltaY * 0.05;
        streetCamera.updateProjectionMatrix();
        time--;
      }
      // camera.position.z -= 10;
    }
  });

  viewer.addEventListener("mousemove", function (event) {
    if (mouseButtonDown) {
      var enableX = 1;
      BaseRotationEuler.set(
        angleRangeRad(
          BaseRotationEuler.x +
            (event.clientY - lastClientY) * MOUSE_SPEED * enableX
        ),
        angleRangeRad(
          BaseRotationEuler.y + (event.clientX - lastClientX) * MOUSE_SPEED
        ),
        0.0
      );
      lastClientX = event.clientX;
      lastClientY = event.clientY;
      mouseX = event.clientX;
      mouseY = event.clientY;
      BaseRotation.setFromEuler(BaseRotationEuler, "YZX");
    }
    mouseX = event.clientX;
    mouseY = event.clientY;
    var x = (mouseX / window.innerWidth) * 20;
    var y = (mouseY / window.innerHeight) * 10 - 20;
  });

  viewer.addEventListener("keypress", function (e) {
    switch (e.keyCode) {
      case 113: // Q
        if (!stop) {
          stop = setInterval(function () {
            autoMoveToNextPlace();
          }, 100);
        }
        break;
      case 119: // W
        moveToNextPlace();
        break;
      case 116: // T
        clearInterval(stop);
        stop = undefined;
        break;
      case 115: // S
        moveToBack();
        break;
      case 97: // A
        turnLeft();
        break;
      case 100: // D
        turnRight();
    }
  });
}

var sliderValue = {
  reset: function () {
    var init_data = [];
    init_data[0] = -2;
    init_data[1] = -2.5;
    init_data[2] = -4;
    init_data[3] = 0;
    init_data[4] = 0;
    init_data[5] = 0;
    for (var i = 0; i < 6; i++) {
      // $(".input_range:eq(" + i + ")").val(init_data[i] * 100);
      // $(".input_text:eq(" + i + ")").val(init_data[i]);
    }
  },
  slideTotext: function (layer) {
    for (var i = 0; i < 6; i++) {
      // var range_value;
      // range_value = $(".input_range:eq(" + i + ")").val();
      // $(".input_text:eq(" + i + ")").val(range_value / 100);
      switch (i) {
        case 0:
          mesh.position.x = range_value / 100;
          break;
        case 1:
          mesh.position.y = range_value / 100;
          break;
        case 2:
          mesh.position.z = range_value / 100;
          break;
        case 3:
          mesh.rotation.x = range_value / 100;
          break;
        case 4:
          mesh.rotation.y = range_value / 100;
          break;
        case 5:
          mesh.rotation.z = range_value / 100;
          break;
      }
    }
  },
};

function initPano(QUALITY) {
  panoLoader = new GSVPANO.PanoLoader();
  panoDepthLoader = new GSVPANO.PanoDepthLoader();
  panoLoader.setZoom(QUALITY);
  panoLoader.onProgress = function (progress) {
    if (progress > 0) {
      // loadingGif.show();
    }
    // loadingGif.setPercent(progress);
  };
  panoLoader.onPanoramaData = function (result) {
    // loadingGif.show();
    // loadingGif.setPercent(0);
  };

  panoLoader.onNoPanoramaData = function (status) {
    alert("no data!");
  };

  panoLoader.onPanoramaLoad = function () {
    var a = THREE.Math.degToRad(90 - parseFloat(panoLoader.heading));
    projSphere.quaternion.setFromEuler(new THREE.Euler(0, a, 0), "YZX");

    projSphere.material.wireframe = false;
    projSphere.material.map.needsUpdate = true;
    projSphere.material.map = new THREE.Texture(this.canvas);
    projSphere.material.map.needsUpdate = true;
    //loadingGif.hide();
  };

  panoDepthLoader.onDepthLoad = function () {
    setSphereGeometry();
  };
}

function setSphereGeometry() {
  var geom = projSphere.geometry;
  var depthMap = panoDepthLoader.depthMap.depthMap;
  var y,
    x,
    u,
    v,
    radius,
    i = 0;
  for (y = 0; y <= geom.heightSegments; y++) {
    for (x = 0; x <= geom.widthSegments; x++) {
      u = x / geom.widthSegments;
      v = y / geom.heightSegments;
      radius = USE_DEPTH ? Math.min(depthMap[y * 512 + x], FAR) : 500;

      var vertex = geom.vertices[i];
      geom.colors[i] = new THREE.Color(0x0099cc);
      vertex.x =
        -radius *
        Math.cos(geom.phiStart + u * geom.phiLength) *
        Math.sin(geom.thetaStart + v * geom.thetaLength);
      vertex.y = radius * Math.cos(geom.thetaStart + v * geom.thetaLength);
      vertex.z =
        radius *
        Math.sin(geom.phiStart + u * geom.phiLength) *
        Math.sin(geom.thetaStart + v * geom.thetaLength);
      i++;
    }
  }
  geom.verticesNeedUpdate = true;
}

function moveToBack() {
  var nextPoint = null;
  var minDelta = 360;
  var navList = panoLoader.links;
  if (navList) {
    for (var i = 0; i < navList.length; i++) {
      var delta = deltaAngleDeg(180 + currHeading, navList[i].yawDeg);

      if (delta < minDelta && delta < NAV_DELTA) {
        minDelta = delta;
        nextPoint = navList[i].panoId;
      }
    }
  }

  if (nextPoint) {
    panoLoader.load(nextPoint, panoLoader.lat, panoLoader.lng);
  }
}

function turnRight() {
  BaseRotationEuler.set(
    angleRangeRad(BaseRotationEuler.x - 0.005),
    angleRangeRad(BaseRotationEuler.y - 0.15),
    0.0
  );
  BaseRotation.setFromEuler(BaseRotationEuler, "YZX");
}

function turnLeft() {
  BaseRotationEuler.set(
    angleRangeRad(BaseRotationEuler.x + 0.005),
    angleRangeRad(BaseRotationEuler.y + 0.15),
    0.0
  );
  BaseRotation.setFromEuler(BaseRotationEuler, "YZX");
}

function moveToNextPlace() {
  var nextPoint = null;
  var minDelta = 360;
  var navList = panoLoader.links;
  if (navList) {
    for (var i = 0; i < navList.length; i++) {
      var delta = deltaAngleDeg(currHeading, navList[i].yawDeg);
      if (delta < minDelta && delta < NAV_DELTA) {
        minDelta = delta;
        nextPoint = navList[i].panoId;
        panoLoader.load(nextPoint, panoLoader.lat, panoLoader.lng);
        // sliderValue.reset();
        break;
      }
    }
  }
}

Array.prototype.min = function () {
  return Math.min.apply(Math, this);
};

function stopAutoMove() {
  clearInterval(stop);
  stop = undefined;
}

function autoMoveToNextPlace() {
  var nextPoint = null;
  var minDelta = 360;
  var navList = panoLoader.links;

  var roadMap = {};
  var roadList = [];
  if (navList) {
    for (var i = 0; i < navList.length; i++) {
      // var delta = panoLoader.heading - navList[i].yawDeg;
      var delta = deltaAngleDeg(currHeading, navList[i].yawDeg);
      roadMap[delta] = navList[i].panoId;
      roadList.push(delta);
    }
  }
  nextPoint = roadMap[roadList.min()];
  if (nextPoint) {
    panoLoader.load(nextPoint, panoLoader.lat, panoLoader.lng);
  }
}

function render() {
  renderer.render(streetScene, streetCamera);
}

function resize(event) {
  WIDTH = window.innerWidth;
  HEIGHT = window.innerHeight;

  renderer.setSize(WIDTH, HEIGHT);
  streetCamera.projectionMatrix.makePerspective(60, WIDTH / HEIGHT, 1, 1100);
}

function loop() {
  requestAnimationFrame(loop);

  // Apply movement
  BaseRotationEuler.set(
    angleRangeRad(BaseRotationEuler.x + moveVector.x),
    angleRangeRad(BaseRotationEuler.y + moveVector.y),
    0.0
  );
  BaseRotation.setFromEuler(BaseRotationEuler, "YZX");

  // Update camera rotation
  streetCamera.quaternion.multiplyQuaternions(BaseRotation, HMDRotation);

  // Compute heading
  headingVector.setFromQuaternion(streetCamera.quaternion, "YZX");
  currHeading = angleRangeDeg(THREE.Math.radToDeg(-headingVector.y));

  // render
  render();
}

// $(document).ready(function () {
//   WIDTH = window.innerWidth;
//   HEIGHT = window.innerHeight;
//   initWebGL();
//   initControls(); // 鼠标、键盘操作
//   window.addEventListener("resize", resize, false); //监听窗口大小变化
//   // var lng = getQueryString('lng');
//   // var lat = getQueryString('lat');
//   // var panoId = getQueryString('panoId');
//   // var QUALITY = getQueryString('zoom');
//   var QUALITY = 3;
//   var i = $("#streetLngVal").text();
//   var lng = i.split(",")[0];
//   var lat = i.split(",")[1];
//   var panoId = i.split(",")[2];
//   initPano(QUALITY);
//   panoLoader.load(panoId, lat, lng);
//   loop(); //相机俯仰角、旋转角变化时，画面重新渲染
// });
